package com.iflytek.yousheng;

import com.iflytek.yousheng.tts.AvatarTts;
import com.iflytek.yousheng.tts.TTSEngineGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class TtsClient {


    private ManagedChannel managedChannel;

    private TTSEngineGrpc.TTSEngineStub ttsEngineStub;

    private CountDownLatch countDownLatch;

    private ByteArrayOutputStream outputStream;


    private StreamObserver<AvatarTts.TTSResponse> mResponseStreamObserver;
    private StreamObserver<AvatarTts.TTSRequest> mRequestStreamObserver;


    public TtsClient(String host, int port) {
        super();
        managedChannel = ManagedChannelBuilder
                .forAddress(host, port)
                .usePlaintext()
                .keepAliveTime(60, TimeUnit.SECONDS)
                .keepAliveTimeout(60, TimeUnit.SECONDS)
                .idleTimeout(60, TimeUnit.SECONDS).build();
        this.ttsEngineStub = TTSEngineGrpc.newStub(managedChannel);
        outputStream = new ByteArrayOutputStream();
        countDownLatch = new CountDownLatch(1);
    }

    private void init() {
        mResponseStreamObserver = new StreamObserver<AvatarTts.TTSResponse>() {
            @Override
            public void onNext(final AvatarTts.TTSResponse response) {
                System.out.println(response.getRetCode() + "==" + response.getRetDesc() + "===" + response.getLastSub());
                try {
                    response.getResult().writeTo(outputStream);
                } catch (IOException e) {
                    e.printStackTrace();
                }

                if (response.getLastSub()) {
                    countDownLatch.countDown();
                    return;
                }
            }

            @Override
            public void onError(final Throwable throwable) {
                throwable.printStackTrace();
                countDownLatch.countDown();
            }

            @Override
            public void onCompleted() {
                System.out.println("complete");
            }

        };
        mRequestStreamObserver = ttsEngineStub.speech(mResponseStreamObserver);

    }

    public void sendText(String vcn, String text) {
        AvatarTts.TTSRequest.Builder request = AvatarTts.TTSRequest.newBuilder()
                .setContent(text)
                .setIsEnd(false)
                .setSessionID(UUID.randomUUID().toString())
                .setTtsMeta(AvatarTts.TTSSessionRequest.newBuilder()
                        .setAppID("gl")
                        .setVoiceName(vcn)
                        .setSub("tts")
                        .setEngineType("ifly")
                        .setCodec(AvatarTts.AudioCodec.newBuilder()
                                .setBit(16)
                                .setChannels(1)
                                .setRate(16000).setFrameSize(0).setFormat("raw"))
                        .setExtPram("ent=xtts,spd=" + 0 + ",vol=" + 20 + ",pit=0")
                        .build());
        mRequestStreamObserver.onNext(request.build());
        System.out.println("发送文本合成: vcn = " + vcn + ",text = " + text);
    }


    /**
     * 关闭客户端
     **/
    public void shutdown() {
        mRequestStreamObserver.onCompleted();
//        mResponseStreamObserver.onCompleted();
        managedChannel.shutdown();
    }


    public static void main(String[] args) throws IOException, InterruptedException {

        String host = "172.31.101.83";
        int port = 41046;

        TtsClient client = new TtsClient(host, port);
        Thread t = new Thread(() -> {
            client.init();
            client.sendText("yezi", "大家好我是科大讯飞小软");

        });
        t.start();
        client.countDownLatch.await();
        FileOutputStream fileOutputStream = new FileOutputStream("c.pcm");
        fileOutputStream.write(client.outputStream.toByteArray());
        client.shutdown();
    }
}